package com.xu.cloud.common.config;

import com.xu.cloud.common.tx.ITransaction;
import com.xu.cloud.common.tx.PlatformITransaction;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.sql.DataSource;

/**
 * 事务 config
 *
 * @author xuguan
 * @since 2024/3/8
 */
@Configuration
@EnableTransactionManagement
@ConditionalOnClass({
        DataSource.class,
        PlatformTransactionManager.class,
        TransactionDefinition.class,
        TransactionStatus.class,
        TransactionAttribute.class,
        TransactionAttributeSource.class
})
@AutoConfigureBefore({
        TransactionAutoConfiguration.class,
        DataSourceTransactionManager.class
})
public class TransactionConfig {

    @Bean
    @ConditionalOnMissingBean
    public TransactionDefinition transactionDefinition() {
        final DefaultTransactionDefinition td = new DefaultTransactionDefinition();
        td.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        td.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        return td;
    }

    @Bean
    @ConditionalOnMissingBean
    public TransactionAttribute transactionAttribute() {
        final DefaultTransactionAttribute ta = new DefaultTransactionAttribute();
        ta.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        ta.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        return ta;
    }

    @Bean
    @ConditionalOnMissingBean
    public TransactionAttributeSource transactionAttributeSource(TransactionAttribute transactionAttribute) {
        return (method, cls) -> transactionAttribute;
    }

    @Bean
    @ConditionalOnMissingBean
    public ITransaction tx(PlatformTransactionManager ptm) {
        return new PlatformITransaction(ptm);
    }
}
